﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Resources;
using System.Globalization;
using System.IO;

using TrainingCenterSystem;
using TrainingCenterSystem.UserManagement;
using TrainingCenterSystem.TestManagement;
using TrainingCenterSystem.VocabularyManagement;

namespace TrainingCenterWinClient.Forms
{
    public partial class TestCreationUpdateForm : Form
    {
        #region private members
        private TrainingCenter _trainingCenter;
        private ResourceManager _resMgr;
        private CollectionHandler _collectionHandler;
        private ArrayList _selectedSources;
        private string _errorNoTestName;
        private string _errorNoNumberOfQuestions;
        private string _errorInvalidFormat;
        private string _errorNoSources;
        private string _errorTooManyQuestions;
        private string _infoSaveFile;
        private TestGenerator _testGenerator;
        #endregion

        public TestCreationUpdateForm(TrainingCenter trainingCenter, CollectionHandler collHandler)
        {
            InitializeComponent();
            _trainingCenter = trainingCenter;
            _collectionHandler = collHandler;
            _selectedSources = new ArrayList();
            _testGenerator = null;
            this.initForm();
        }

        #region methods
        private void initForm()
        {
            // init language
            this.UpdateLanguage(_trainingCenter.CurrentLanguageID);

            // initSupervisorGroup
            this.initSupervisorGroupBox();

            // init list of sources
            this.initSourceList();

            // init type
            this.initTestType();

            // init level
            this.initTestLevel();

            this.initTestDirection();

            this.initRadioButtons();

            this.btnRemoveSource.Enabled = false;

            if (_trainingCenter.IsBasicVersion)
            {
                this.radioTraining.Checked = true;
                this.radioTest.Enabled = false;
                this.cmbTestLevel.Enabled = false;
                this.cmbTestType.Enabled = false;
                this.cmbTestDirection.Enabled = false;
                this.btnSaveOrUpdate.Enabled = false;
            }
        }

        private void initRadioButtons()
        {
            this.radioTraining.Checked=true;
            if (_trainingCenter.CurrentUser is Student)
            {
                this.radioTest.Enabled = false;
            }
        }

        /// <summary>
        /// Initializes the test type
        /// </summary>
        private void initTestType()
        {
            this.cmbTestType.Items.Clear();
            this.cmbTestType.Items.Add(_resMgr.GetString("TestType_FreeText"));
            this.cmbTestType.Items.Add(_resMgr.GetString("TestType_MultipleChoice"));
            this.cmbTestType.Items.Add(_resMgr.GetString("TestType_Mixed"));
            this.cmbTestType.SelectedIndex = 0;
        }

        /// <summary>
        /// Initializes the test level
        /// </summary>
        private void initTestLevel()
        {
            this.cmbTestLevel.Items.Clear();
            this.cmbTestLevel.Items.Add(_resMgr.GetString("TestLevel_Basic"));
            this.cmbTestLevel.Items.Add(_resMgr.GetString("TestLevel_Extended"));
            this.cmbTestLevel.SelectedIndex = 0;
        }

        /// <summary>
        /// Initializes the test direction
        /// </summary>
        private void initTestDirection()
        {
            this.cmbTestDirection.Items.Clear();
            this.cmbTestDirection.Items.Add(_resMgr.GetString("TestDirection_BaseToTranslation"));
            this.cmbTestDirection.Items.Add(_resMgr.GetString("TestDirection_TranslationToBase"));
            this.cmbTestDirection.Items.Add(_resMgr.GetString("TestDirection_Mixed"));
            this.cmbTestDirection.SelectedIndex = 1;
        }

        /// <summary>
        /// Initializes the listbox of selected sources
        /// </summary>
        private void initSourceList()
        {
            this.listSources.Items.Clear();
        }

        /// <summary>
        /// Initializes the groupbox for supervisor tasks
        /// </summary>
        private void initSupervisorGroupBox()
        {
            if (_trainingCenter.CurrentUser is Student)
                this.grpSupervisorTasks.Enabled = false;
            else
            {
                this.grpSupervisorTasks.Enabled = true;
                DateTime now = new DateTime(2009, 7, 23);
                this.testdatePicker.MinDate = now;
                this.testdatePicker.MaxDate = now.AddDays(14);
                this.chkPublic.Checked = false;                
                this.initHours();
                this.initMinutes();
            }
        }

        /// <summary>
        /// Initializes the combobox for the hours
        /// </summary>
        private void initHours()
        {
            this.cmbHours.Items.Clear();
            for (int i = 0; i < 4; i++)
                this.cmbHours.Items.Add(i);
            this.cmbHours.SelectedIndex = 1;
        }

        /// <summary>
        /// Initializes the combobox for the minutes
        /// </summary>
        private void initMinutes()
        {
            this.cmbMinutes.Items.Clear();
            for (int i = 0; i < 60; i++)
                this.cmbMinutes.Items.Add(i);
            this.cmbMinutes.SelectedIndex = 1;
        }

        /// <summary>
        /// Updates the language of the form
        /// </summary>
        /// <param name="langID">the language-ID</param>
        private void UpdateLanguage(string langID)
        {
            try
            {
                // Set Language
                Thread.CurrentThread.CurrentUICulture = new CultureInfo(langID);

                // Init ResourceManager
            _resMgr =
                    new ResourceManager("TrainingCenterWinClient.ReStrings",
                    typeof(TestCreationUpdateForm).Assembly);

                // assign localized strings to UI                
                this.Text = _resMgr.GetString("TestCreationForm_caption");
                this.lblTestName.Text = _resMgr.GetString("TestCreationForm_lblTestName");
                this.lblTestDescription.Text = _resMgr.GetString("TestCreationForm_lblTestDescription");
                this.lblTestType.Text = _resMgr.GetString("TestCreationForm_lblTestType");
                this.lblTestLevel.Text = _resMgr.GetString("TestCreationForm_lblTestLevel");
                this.lblNoQuestions.Text = _resMgr.GetString("TestCreationForm_lblNoQuestions");
                this.lblHours.Text = _resMgr.GetString("TestCreationForm_lblHours");
                this.lblMinutes.Text = _resMgr.GetString("TestCreationForm_lblMinutes");
                this.lblStartTime.Text = _resMgr.GetString("TestCreationForm_lblStartTime");
                this.lblDuration.Text = _resMgr.GetString("TestCreationForm_lblDuration");
                this.chkPublic.Text = _resMgr.GetString("TestCreationForm_chkPublic");
                this.lblSources.Text = _resMgr.GetString("TestCreationForm_lblSources");
                this.lblTestDirection.Text = _resMgr.GetString("TestCreationForm_lblTestDirection");
                this.btnAddSource.Text = _resMgr.GetString("TestCreationForm_btnAddSource");
                this.btnRemoveSource.Text = _resMgr.GetString("TestCreationForm_btnRemoveSource");
                this.btnGenerate.Text = _resMgr.GetString("TestCreationForm_btnGenerate");
                this.btnSaveOrUpdate.Text = _resMgr.GetString("TestCreationForm_btnSave");
                this.radioTest.Text = _resMgr.GetString("TestCreationForm_radioTest");
                this.radioTraining.Text = _resMgr.GetString("TestCreationForm_radioTraining");
                this.grpSupervisorTasks.Text = _resMgr.GetString("TestCreationForm_grpSup");
                this.grpGeneral.Text = _resMgr.GetString("TestCreationForm_grpGeneral");
                this.grpTestSources.Text = _resMgr.GetString("TestCreationForm_grpTestSources");

                _errorInvalidFormat = _resMgr.GetString("TestCreationForm_ErrorInvalidFormat");
                _errorNoNumberOfQuestions = _resMgr.GetString("TestCreationForm_ErrorNoQuestions");
                _errorNoSources = _resMgr.GetString("TestCreationForm_ErrorNoSources");
                _errorNoTestName = _resMgr.GetString("TestCreationForm_ErrorNoTestName");
                _errorTooManyQuestions = _resMgr.GetString("TestCreationForm_ErrorTooManyQuestions");
                _infoSaveFile = _resMgr.GetString("TestCreationForm_infoSaveFile");

                //this.btnOpenTest.Text = _resMgr.GetString("TestMainForm_btnOpenTest");
                //this.btnViewTest.Text = _resMgr.GetString("TestMainForm_btnViewTest");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        #endregion

        /// <summary>
        /// Opens the TestSourceForm
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnAddSource_Click(object sender, EventArgs e)
        {
            TestSourceForm sourceForm = new TestSourceForm(_trainingCenter, _collectionHandler, _selectedSources);
            sourceForm.ShowDialog();
            this.updateSourceList();
        }

        /// <summary>
        /// Updates the list of selected sources
        /// </summary>
        private void updateSourceList()
        {
            this.listSources.Items.Clear();
            for (int i = 0; i < _selectedSources.Count; i++)
            {
                if (_selectedSources[i] is VocabularyCollection) // if it is a collection
                    this.listSources.Items.Add(((VocabularyCollection)_selectedSources[i]).CollectionName);
                else if (_selectedSources[i] is VocabularyContext) // if it is a context
                    this.listSources.Items.Add(((VocabularyContext)_selectedSources[i]).ContextName);                
            }
        }

        /// <summary>
        /// Chooses a source from the listbox
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void listSources_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.listSources.SelectedIndex < 0)
                this.btnRemoveSource.Enabled = false;
            else
                this.btnRemoveSource.Enabled = true;
        }

        /// <summary>
        /// Generates a test/training
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnGenerate_Click(object sender, EventArgs e)
        {
            // read the general attributes
            string name = this.txtTestName.Text;
            string description = this.txtTestDescription.Text;
            byte noOfQuestions = 0;

            // check if the name is entered
            if (name.Length == 0)
            {
                MessageBox.Show(_errorNoTestName);
                return;
            }

            // check if number of question is entered
            if (this.txtNoQuestions.Text.Length == 0)
            {
                MessageBox.Show(_errorNoNumberOfQuestions);
                return;
            }
                        
            // check if the number of questions is the right format
            try
            {
                noOfQuestions = Convert.ToByte(this.txtNoQuestions.Text);
            }
            catch (FormatException fexc)
            {
                MessageBox.Show(_errorInvalidFormat);
            }
            catch (OverflowException oexc)
            {
                MessageBox.Show(_errorInvalidFormat);
            }

            // set test direction
            int iTestDirection = this.cmbTestDirection.SelectedIndex;
            TestDirection testDirection;

            if (iTestDirection == 0)
                testDirection = TestDirection.BaseToTranslation;
            else if (iTestDirection == 1)
                testDirection = TestDirection.TranslationToBase;
            else
                testDirection = TestDirection.Mixed;

            // set test level and type
            int iTestLevel = this.cmbTestLevel.SelectedIndex;
            int iTestType = this.cmbTestType.SelectedIndex;
            TestLevel level;
            TestType type;

            if (iTestLevel > 0)
                level = TestLevel.Extended;
            else
                level = TestLevel.Basic;

            if (iTestType == 1)
                type = TestType.Mixed;
            else if (iTestType == 0)
                type = TestType.FreeText;
            else
                type = TestType.MultipleChoice;

            // check selected sources
            if (_selectedSources.Count == 0)
            {
                MessageBox.Show(_errorNoSources);
                return;
            }

            // generate the test                        
            _testGenerator = new TestGenerator(name, description, noOfQuestions, level, type, testDirection, _selectedSources, _collectionHandler);
            _testGenerator.TransformSources();

            //check if enough sources have been selected
            if (_testGenerator.Sources.Count >= noOfQuestions)
            {
                _testGenerator.GenerateQuestions();
            }
            else
            {
                MessageBox.Show(_errorTooManyQuestions + _testGenerator.Sources.Count.ToString());
                return;
            }

            // show save file-dialog
            if (this.saveFile(_testGenerator.VocTraining)) 
            {
                TestExecutionForm testExecForm = new TestExecutionForm(_trainingCenter, _testGenerator.VocTraining,_testGenerator.Sources);
                testExecForm.ShowDialog();
            }
            else            
                MessageBox.Show(_infoSaveFile); 

        }

        /// <summary>
        /// Saves a file for vocabuilary training or test
        /// </summary>
        /// <param name="aTraining">a training object</param>
        /// <returns>true, if saving was successful, otherwise false</returns>
        private bool saveFile(VocabularyTraining aTraining)
        {
            //1. init the save file dialog            
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.DefaultExt = "xml";
            saveFileDialog.Filter = "Xml File|*.xml";
            saveFileDialog.InitialDirectory = "../testfiles";
            DialogResult result = saveFileDialog.ShowDialog();
            if (result == DialogResult.Cancel)
                return false;
                        
            //2. write the file
            string filename = saveFileDialog.FileName;
            _testGenerator.VocTraining.TestID = filename;
            TestFileWriter fileWriter = new TestFileWriter(_testGenerator.VocTraining, filename);
            return true;
        }

        /// <summary>
        /// Selects training or test
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void radioTraining_CheckedChanged(object sender, EventArgs e)
        {
            if (this.radioTraining.Checked)
                this.grpSupervisorTasks.Enabled = false;
            else
                this.grpSupervisorTasks.Enabled = true;
        }

        private void groupBox2_Enter(object sender, EventArgs e)
        {

        }

        private void groupBox1_Enter(object sender, EventArgs e)
        {

        }

        private void tableLayoutPanel1_Paint(object sender, PaintEventArgs e)
        {

        }

        private void lblNoQuestions_Click(object sender, EventArgs e)
        {

        }

        private void cmbTestLevel_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void TestCreationUpdateForm_Load(object sender, EventArgs e)
        {
            //this.btnRemoveSource
            ToolTip tt = new ToolTip();
            //btnRemoveSource.
        }

        private void toolStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {

        }
    }
}
